using System;
using System.Collections.Specialized;
using System.Collections.Generic;
using System.Text;
using Lucene.Net.Index;
using Lucene.Net.Search;
using Lucene.Net.Store;
using Lucene.Net.Analysis.Standard;
using Lucene.Net.Documents;
using Bots.Search;
using System.Configuration;
using Bots.Index;

namespace Bots
{
    public class IndexBuilder
    {
        private readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(IndexBuilder));
        private List<ActiveObject> list = null;
        private static IndexBuilder builder = null;
        private bool isRunning = false;

        /// <summary>
        /// don't invoke MemoryIncIndexProvider's IncIndexAdd method when IsRunning is false, keep data from being losed.
        /// </summary>
        public bool IsRunning {
            get {
                return isRunning;
            }
        }

        protected IndexBuilder() {
            list = new List<ActiveObject>();
        }

        static public IndexBuilder Instance {
            get {
                if (builder == null) {
                    builder = new IndexBuilder();
                }
                return builder;
            }
        }

        public static void RebuildIndex() {
            SearchConfig.Init();
            NameValueCollection dirs = SearchConfig.IndexDirectorys;
            for (int i = 0; i < dirs.Count; i++)
            {
                string dir = dirs[i];
                Lucene.Net.Store.Directory directory = Lucene.Net.Store.FSDirectory.GetDirectory(dir, true); 
                IndexWriter indexWriter = new IndexWriter(dir, new StandardAnalyzer(), true);
                indexWriter.Close();
            }
        }

    
        public void Start()
        {
            SearchConfig.Init();

            ActiveObject consumer = new ActiveObject();
            MutexTask indexWriterTasker = new IndexWriterTasker();
            InstantScheduler scheduler = new InstantScheduler(indexWriterTasker);
            consumer.AddScheduler(scheduler);

            int indexOptimizationInterval = 10000;
            if(!string.IsNullOrEmpty(ConfigurationManager.AppSettings["indexOptimizationInterval"])){
                indexOptimizationInterval = Convert.ToInt32(ConfigurationManager.AppSettings["indexOptimizationInterval"]);
            }         
   
            MutexTask indexOptimizateTasker = new IndexOptimizateTasker();
            TimeIntervalScheduler oscheduler = new TimeIntervalScheduler(indexOptimizateTasker, indexOptimizationInterval);
            consumer.AddScheduler(oscheduler);

            MutexTask indexUpdateTasker = new IndexUpdateTasker();
            scheduler = new InstantScheduler(indexUpdateTasker);
            consumer.AddScheduler(scheduler);

            ITask dependencyTasker = new DependencyTasker();
            scheduler = new InstantScheduler(dependencyTasker);
            consumer.AddScheduler(scheduler);

            List<IMutexTask> mutexTasks = new List<IMutexTask>();
            mutexTasks.Add(indexUpdateTasker);
            indexWriterTasker.MutexTasks = mutexTasks;

            mutexTasks = new List<IMutexTask>();
            mutexTasks.Add(indexWriterTasker);
            mutexTasks.Add(indexOptimizateTasker);
            indexUpdateTasker.MutexTasks = mutexTasks;

            mutexTasks = new List<IMutexTask>();
            mutexTasks.Add(indexWriterTasker);
            indexOptimizateTasker.MutexTasks = mutexTasks;
            list.Add(consumer);
            consumer.RunInThread();

            ActiveObject producer = new ActiveObject();
            int fetcherInterval = 1000;
            if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["fetcherInterval"]))
            {
                fetcherInterval = Convert.ToInt32(ConfigurationManager.AppSettings["fetcherInterval"]);
            }
            Fetcher fetcher = new Fetcher();
            TimeIntervalScheduler fetcherScheduler = new TimeIntervalScheduler(fetcher, fetcherInterval);
            producer.AddScheduler(fetcherScheduler);

            ITask idleTasker = new IdleTasker(500);
            scheduler = new InstantScheduler(idleTasker);
            producer.AddScheduler(scheduler);

            list.Add(producer);
            producer.RunInThread();

            isRunning = true;
        }

        public void Stop() {
            isRunning = false;
            foreach(ActiveObject ao in list){
                ao.Stop();
            }
            list.Clear();
        }
          
    }
}
